package tests;

import static org.junit.Assert.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import com.thoughtworks.xstream.XStream;

import de.dfki.asr.genesis2.sms.util.SocialEvent;
import de.dfki.asr.genesis2.sms.util.SocialPOIXML;
import de.dfki.asr.genesis2.sms.util.SocialPOIXMLList;
import de.dfki.asr.genesis2.sms.util.User;

public class LocationSearch {
	
	private HttpClient client = null;

	private HttpResponse executeRequest(String query, String location, String radius, String maxResults, String sources) throws ClientProtocolException, IOException {
		String url = "http://localhost:8080/sms/search?";
		
    	if (query!= null)
    		url += "&q=" + query;
    	if (location!= null) 
    		url += "&location=" + location;
    	if (radius!= null) 
    		url += "&radius=" + radius;
    	if (maxResults!= null) 
    		url += "&max-results=" + maxResults;
    	if (sources!= null) 
    		url += "&sources=" + sources;
    	
    	System.out.println(url);
    	
    	HttpGet get = new HttpGet(url);
		return client.execute(get);
	}
	
	@Test
	public void test() throws ClientProtocolException, IOException, InterruptedException {
		
		Integer maxResults;
		Integer maxSources;
		String radius;
		String location;
		String query;
		String sources;
		
		
		HttpResponse resp = null;
		String body = null;
		SocialPOIXMLList pois = null;
		int statusCode;

		XStream xstream = new XStream();
		xstream.processAnnotations(SocialPOIXMLList.class);
		
		client = new DefaultHttpClient();
		
		//Default correct values for the parameters
		maxResults = 5;
		maxSources = 3;
		radius = "45mi";
		location = "37.42307,-122.08427";
		query = "golden+gate";
		sources = "youtube,twitter,flickr";
		
		//Test valid request with both sources
		resp = executeRequest(query, location, radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		//System.out.println(body);
		//pois = (SocialPOIXMLList)xstream.fromXML(body);
		System.out.println(body);
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//assertEquals(maxResults*maxSources, pois.getEntries().size());
		
		
		//Tests for Parameter SOURCES
		//Test valid request with source=Youtube
		resp = executeRequest(query, location, radius, maxResults.toString(), "youtube");
		body = EntityUtils.toString(resp.getEntity());
		pois = (SocialPOIXMLList)xstream.fromXML(body);
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		assertEquals(maxResults.intValue(), pois.getEntries().size());	
		//Test valid request with source=Twitter
		resp = executeRequest(query, location, radius, maxResults.toString(), "twitter");
		body = EntityUtils.toString(resp.getEntity());
		pois = (SocialPOIXMLList)xstream.fromXML(body);
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		assertEquals(maxResults.intValue(), pois.getEntries().size());		
		//Test valid request with empty source (should return both)
		resp = executeRequest(query, location, radius, maxResults.toString(), "");
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Test valid request without source field
		resp = executeRequest(query, location, radius, maxResults.toString(), null);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Test valid request with both sources
		resp = executeRequest(query, location, radius, maxResults.toString(), "abc");
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Test valid request with both sources
		resp = executeRequest(query, location, radius, maxResults.toString(), "twitterabc");
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Test valid request with both sources
		resp = executeRequest(query, location, radius, maxResults.toString(), "youtubetwitterabc");
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		
		//Test for parameter LOCATION
		//Latitude out of bounds
		resp = executeRequest(query, "-91,120", radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Longitude out of bounds
		resp = executeRequest(query, "-81,190", radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Invalid format
		resp = executeRequest(query, "-81.190", radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Invalid format
		resp = executeRequest(query, "-abc.190", radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Null value
		resp = executeRequest(query, null, radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Empty value
		resp = executeRequest(query, "", radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		
		//Test for parameter RADIUS
		//No distance unit integer
		resp = executeRequest(query, location, "10", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//No distance unit float
		resp = executeRequest(query, location, "15.9", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Containing distance
		resp = executeRequest(query, location, "15mi", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Invalid format
		resp = executeRequest(query, location, "12,9m", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Invalid character
		resp = executeRequest(query, location, "129x", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Null value
		resp = executeRequest(query, location, null, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Empty value
		resp = executeRequest(query, location, "", maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		
		//Test for parameter MAX-RESULTS
		//Float
		resp = executeRequest(query, location, radius, "20.1", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Sharp float
		resp = executeRequest(query, location, radius,"20.0", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Invalid format
		resp = executeRequest(query, location, radius, "15mi", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Out of bounds
		resp = executeRequest(query, location, radius, "55", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Zero
		resp = executeRequest(query, location, radius, "0", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Negative
		resp = executeRequest(query, location, radius, "-10", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Null value
		resp = executeRequest(query, location, radius, null, sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		//Empty value
		resp = executeRequest(query, location, radius, "", sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 200);
		
		//Test for parameter QUERY
		//Null value
		resp = executeRequest(null, location, radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);
		//Empty value
		resp = executeRequest("", location, radius, maxResults.toString(), sources);
		body = EntityUtils.toString(resp.getEntity());
		statusCode = resp.getStatusLine().getStatusCode();
		assertEquals(statusCode, 400);

	}

}
